package com.taxi.driver.socket;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.text.TextUtils;

import com.alibaba.fastjson.JSON;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.model.LatLng;
import com.qianxx.utils.RxUtil;
import com.qianxx.utils.TypeUtils;
import com.socks.library.KLog;
import com.taxi.driver.R;
import com.taxi.driver.common.AppConfig;
import com.taxi.driver.common.Application;
import com.taxi.driver.config.BizStatus;
import com.taxi.driver.config.IConstants;
import com.taxi.driver.config.PositionType;
import com.taxi.driver.data.amap.AMapManager;
import com.taxi.driver.data.entity.UploadOrderEntity;
import com.taxi.driver.data.order.OrderRepository;
import com.taxi.driver.data.user.UserRepository;
import com.taxi.driver.event.MapEvent;
import com.taxi.driver.event.MsgEvent;
import com.taxi.driver.event.NetworkEvent;
import com.taxi.driver.event.OrderEvent;
import com.taxi.driver.event.UserEvent;
import com.taxi.driver.module.main.MainActivity;
import com.taxi.driver.module.main.mine.message.details.MessageDetailsActivity;
import com.taxi.driver.module.main.mine.wallet.MyWalletActivity;
import com.taxi.driver.module.order.detail.OrderDetailActivity;
import com.taxi.driver.module.order.popup.OrderPopupActivity;
import com.taxi.driver.module.vo.MessageVO;
import com.taxi.driver.socket.message.GetLocationOrderMessage;
import com.taxi.driver.socket.message.GetLocationOrderResponseMessage;
import com.taxi.driver.socket.message.HeartBeatMessage;
import com.taxi.driver.socket.message.LoginMessage;
import com.taxi.driver.socket.message.LoginResponseMessage;
import com.taxi.driver.socket.message.PushMessage;
import com.taxi.driver.socket.message.PushResponseMessage;
import com.taxi.driver.socket.message.UploadLocationMessage;
import com.taxi.driver.socket.message.UploadLocationResponseMessage;
import com.taxi.driver.socket.message.base.Message;
import com.taxi.driver.util.ScreenUtil;
import com.taxi.driver.util.SpeechUtil;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Random;

import javax.inject.Inject;

/**
 * 功能描述：处理"长链接"相关操作的Service
 */
public class SocketService extends Service implements AMapLocationListener {

    @Inject
    UserRepository mUserRepository;
    @Inject
    AMapManager mAMapManager;

    private static String wsUrl = "";
    private static ServiceReadyListener mListener;
    // 定位对象
    public AMapLocationClient mLocationClient;

    private int mCarLevelType;
    private int mLocationFailCount = 0;
    private int mSocketFailCount = 0;
    private boolean isTimingSend = true;
    private String token;
    private String clientUuid;
    private SocketClient mClient;
    private NotificationManager mManager;

    @Inject
    OrderRepository mOrderRepository;

    /**
     * 启动Service
     *
     * @param context
     * @param listener
     */
    public static void startService(Context context, ServiceReadyListener listener) {
        mListener = listener;
        startService(context);
    }

    /**
     * 启动Service
     *
     * @param context
     */
    public static void startService(Context context) {
        Intent intent = new Intent(Intent.ACTION_MAIN).setClass(context, SocketService.class);
        context.startService(intent);
    }

    public static void stopService(Context context) {
        context.stopService(new Intent(Intent.ACTION_MAIN).setClass(context, SocketService.class));
    }

    @Override
    public void onCreate() {
        super.onCreate();
        wsUrl = AppConfig.WS;
        EventBus.getDefault().register(this); //注册监听
        Application.getAppComponent().inject(this); //依赖注入
        startLoacation(); //开启定位

        if (mUserRepository.isLogin()) {
            setNotification("欢迎回来，正在连接服务器......");
        }

        mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mListener != null) {
            mListener.onReady();
        }
        return super.onStartCommand(intent, flags, startId);
    }

    private void setNotification(String text) {
        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        // 提升应用权限
        Notification notification = new Notification.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(getString(R.string.app_name))
                .setContentText(text)
                .setContentIntent(pi)
                .build();
        startForeground(10000, notification);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this); //注销监听
        mClient = null;
        mAMapManager.finishLocation();
        stopForeground(true);
        removeTimer();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    public interface ServiceReadyListener {
        void onReady();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onSocketEvent(SocketEvent event) {
        switch (event.type) {
            case SocketEvent.DISCONNECT: //断开连接
                KLog.e("===========断开长链接======");
                disconnect();
                stopForeground(true);
                break;
            case SocketEvent.CONNECT: //开启长连接
                KLog.e("===========开启长链接======");
                if (mClient != null && mClient.isOpen()) {//上一次的长链接已被打开并且未被关闭时
                    //检查当前用户的token和上一次长链接的token是否一致
                    mUserRepository.getUserInfo()
                            .compose(RxUtil.applySchedulers())
                            .subscribe(entity -> {
                                /* token不一致，则重连 */
                                if (!entity.token.equals(token)) {
                                    connect();
                                }
                            }, KLog::e);
                } else {
                    connect();
                }
                break;
            case SocketEvent.GET_LAST_SPECIAL_INFO: //获取专车最近一次上传的信息
                KLog.e("===========获取专车最近一次上传的信息======");
                if (event.obj1 == null) return;
                if (mClient != null) mClient.sendGetLocationOrder((String) event.obj1);
                break;
            case SocketEvent.SET_SPECIAL_INFO: //设置专车里程信息
                KLog.e("===========设置专车里程信息======");

                if (event.obj1 == null) return;
                mUpload = (UploadOrderEntity) event.obj1;
                mCurrentPoint = mUpload.currentPoint;
                break;
            case SocketEvent.SET_SPECIAL_INFO_RIGHT_NOW: //立即上传专车里程消息
                KLog.e("===========立即上传专车里程消息======");
                if (event.obj1 == null) return;
                mUpload = (UploadOrderEntity) event.obj1;
                mCurrentPoint = mUpload.currentPoint;

                if (mClient != null) {
                    mClient.sendLocationMessage(uploadLocationByTiming());
                }
                break;
            case SocketEvent.ARRIVE_DEST: //重置信息
                mUpload = null;
                break;
            case SocketEvent.WORKING_STATUS://出车，允许发送定位位置
                KLog.e("===========出车，允许发送定位位置======");
                if (mClient == null) {
                    connect();
                }
                isTimingSend = (boolean) event.obj1;
                if (isTimingSend) {
                    setNotification("听单中，订单马上就来");
                } else {
                    setNotification("您已收车，点击出车开始听单");
                }
                break;
            case SocketEvent.BIZ_STATUS://设置订单号
                KLog.e("===========设置订单号======");
                bizStatus = (int) event.obj1;
                orderUuid = (String) event.obj2;
                break;
            case SocketEvent.SEND_POSITION:
                KLog.e("===========SEND_POSITION======");
                if (mClient == null) {
                    connect();
                }
                int bizStatus = (int) event.obj1;
                String positionType = (String) event.obj2;
                String orderUuid = (String) event.obj3;

                if (PositionType.SJSB.equals(positionType)) {
                    mClient.sendLoginMessage();
                    mClient.uploadSuccess = true;
                    positionType = PositionType.TEST;
                }
                if (PositionType.SJXB.equals(positionType)) {
                    isTimingSend = false;
                    setNotification("您已收车，点击出车开始听单");
                    return;
                }
                if (mClient != null && mCurrentPoint != null && mCurrentPoint.latitude != 0d && mCurrentPoint.longitude != 0d) {
                    UploadLocationMessage message = uploadLocationByTrigger(bizStatus, positionType, orderUuid);
                    mClient.sendLocationMessage(message);
                }
                break;
        }
    }

    private void connect() {
        try {
            URI uri = new URI(wsUrl);
            mClient = new SocketClient(uri); // 创建长链接
            mClient.connect(); // 开启长连接
            KLog.e("=====长链接开始链接===");
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        removeTimer();
        handler.postDelayed(timeRunable, 5000);
    }

    private void disconnect() {
        removeTimer();
        if (mClient != null && mClient.isOpen()) {
            mClient.close();
        }
        mClient = null;
        token = null;
        clientUuid = null;
    }

    private Handler handler = new Handler();
    private Runnable timeRunable = new Runnable() {
        @Override
        public void run() {
            handler.removeCallbacks(timeRunable);

            if (mClient != null && mClient.isSocketLogin) {
                mClient.upload();
                if (mLocationFailCount == 0) {
                    if (isTimingSend) {
                        setNotification("听单中，订单马上就来");
                    } else {
                        setNotification("您已收车，点击出车开始听单");
                    }
                } else {
                    if (mLocationFailCount < 60) {
                        setNotification("定位失败，正在重新定位......");
                    } else {
                        setNotification("多次定位失败，已停止接单，请检测定位服务。");
                    }
                }
            } else {
                connect();
                if (mSocketFailCount < 60) {
                    setNotification("连接失败，正在重连......");
                } else {
                    setNotification("服务器多次连接失败，已经离线，请检查网络");
                }
            }

            handler.postDelayed(timeRunable, 15000);
        }
    };

    /**
     * 移除定时器
     */
    private void removeTimer() {
        if (timeRunable != null) {
            handler.removeCallbacks(timeRunable);
        }
    }

    /**
     * WebSocketClient，用于监听"长链接"消息
     */
    private class SocketClient extends WebSocketClient {

        private final static int INTERVAL = 15 * 1000; //发送心跳的时间间隔15秒

        private int heartBeatCount; //记录心跳次数，收到推送消息时，需置空；一旦超过3次，重连。
        private long receiveStamp; //最近一次收到推送的时间戳
        private boolean isSocketLogin = false; //只有收到"登录反馈报文"，才算真正与服务端连接
        private boolean uploadSuccess = false;

        private void upload() {
            if (getElapsedTime() > INTERVAL) {//检查服务端长链接是否已经断开
                if (heartBeatCount >= 3) { //3次心跳，没收到"反馈报文"，则重连
                    SocketService.this.connect();
                    return;
                }
                heartBeatCount++;
                sendHeartBeatMessage();
            }
            // 发送定位报文
            if (isTimingSend) {
                sendLocationMessage(uploadLocationByTiming());
            }
        }

        private long getElapsedTime() { //距离最近一次收到消息的时间差
            return System.currentTimeMillis() - receiveStamp;
        }

        private SocketClient(URI serverURI) {
            super(serverURI);
        }

        /**
         * 长链接启动
         *
         * @param serverHandshake
         */
        @Override
        public void onOpen(ServerHandshake serverHandshake) {
            KLog.i("长链接已启动");
            isSocketLogin = false;
            mUserRepository.getUserInfo()
                    .compose(RxUtil.applySchedulers())
                    .subscribe(entity -> {
                        token = entity.token;
                        clientUuid = entity.uuid;
                        mCarLevelType = entity.carLevelType;
                        sendLoginMessage(); //发送登录报文
                    }, KLog::e);
        }

        /**
         * 收到长链接推送
         *
         * @param message
         */
        @Override
        public void onMessage(String message) {
            KLog.e(JSON.toJSONString(message));
            /* 收到消息 */
            receiveStamp = System.currentTimeMillis();
            heartBeatCount = 0; //必需
            if (TextUtils.isEmpty(message)) return;
            try {
                Message msg = JSON.parseObject(message, Message.class);
                switch (msg.getType()) {
                    case LOGIN_RESPONSE: //登录反馈报文
                        KLog.e("-------------------收到，登录反馈报文\n" + message);
                        LoginResponseMessage loginMessage = JSON.parseObject(message, LoginResponseMessage.class);
                        isSocketLogin = loginMessage.getSuccess(); //是否真正连接成功
                        if (isSocketLogin) {
                            mSocketFailCount = 0;
                            EventBus.getDefault().post(new NetworkEvent(NetworkEvent.SOCKET_SUCCESS));
                        } else {
                            mSocketFailCount++;
                            EventBus.getDefault().post(new NetworkEvent(NetworkEvent.SOCKET_FAILED));
                        }
                        break;
                    case PUSH: //推送报文
                        KLog.e("------------------推送报文---\n" + message);
                        PushMessage pushMessage = JSON.parseObject(message, PushMessage.class);
                        String pushUuid = dealwithPushMessage(pushMessage); /* 处理推送 */
                        if (!TextUtils.isEmpty(pushUuid))
                            sendPushResponseMessage(pushUuid); //发送推送反馈报文（告知服务端已收到）
                        break;
                    case UPLOAD_LOCATION_RESPONSE: //上传位置反馈报文
                        KLog.e("------------------上传位置反馈报文---\n" + message);
                        if (uploadSuccess) {
                            EventBus.getDefault().post(new NetworkEvent(NetworkEvent.UPLOAD_SUCCESS));
                            uploadSuccess = false;
                            isTimingSend = true;
                            setNotification("听单中，订单马上就来");
                        }

                        UploadLocationResponseMessage uploadLocationResponseMessage = JSON.parseObject(message, UploadLocationResponseMessage.class);
                        if (TextUtils.isEmpty(uploadLocationResponseMessage.getOrderUuid())) return;
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.SPECIAL_PRICE,
                                uploadLocationResponseMessage.getOrderUuid(),
                                TypeUtils.getValue(uploadLocationResponseMessage.getTotalFare()))); //将专车金额发送出来
                        break;
                    case HEART_BEAT: //心跳反馈报文,无需处理，记录heartBeatCount即可
                        KLog.e("-----收到，心跳反馈报文");
                        break;
                    case GET_LOCATION_ORDER_RESPONSE: //获取最近一次"专车里程信息"的反馈报文
                        KLog.e("--------------------收到，最近一次专车里程信息的反馈报文\n" + message);
                        GetLocationOrderResponseMessage responseMessage = JSON.parseObject(message, GetLocationOrderResponseMessage.class);
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.LAST_SPECIAL_INFO, responseMessage)); //发送出来
                        break;
                }
            } catch (Exception e) {
                uploadErrorMsg(e.toString(), e.getMessage());
                KLog.e("解析数据出现异常");
                e.printStackTrace();
            }
        }

        @Override
        public void onClose(int code, String reason, boolean remote) {
            /* 长链接关闭 */
            KLog.e("----------长链接关闭");
            isSocketLogin = false;
            mSocketFailCount++;
            EventBus.getDefault().post(new NetworkEvent(NetworkEvent.SOCKET_FAILED));
            uploadErrorMsg(code + "", reason);
        }

        @Override
        public void onError(Exception ex) {
            /* 长链接出现异常 */
            KLog.e("-----------长链接出现异常");
            uploadErrorMsg(ex.toString(), ex.getMessage());
        }

        /**
         * 发送登录报文
         */
        private void sendLoginMessage() {
            LoginMessage loginMessage = new LoginMessage(LoginMessage.From.DRIVER);
            loginMessage.setToken(token);
            loginMessage.setClientUuid(clientUuid);
            String json = JSON.toJSONString(loginMessage);
            send(json); //发送登录报文
            KLog.e("------------发送，登录报文\n" + json);
        }

        /**
         * 发送心跳报文
         */
        private void sendHeartBeatMessage() {
            HeartBeatMessage heartBeatMessage = new HeartBeatMessage(clientUuid);
            heartBeatMessage.setClientUuid(clientUuid);
            String json = JSON.toJSONString(heartBeatMessage);
            send(json); //发送心跳报文
            KLog.e("发送，心跳报文\n" + json);
        }

        /**
         * 发送推送反馈报文
         */
        private void sendPushResponseMessage(String pushUuid) {
            PushResponseMessage pushResponseMessage = new PushResponseMessage(pushUuid, true, "");
            pushResponseMessage.setClientUuid(clientUuid);
            pushResponseMessage.setToken(token);
            String json = JSON.toJSONString(pushResponseMessage);
            send(json); //发送推送反馈报文
            KLog.e("--------------发送，推送反馈报文\n" + json);
        }

        /**
         * 发送地址报文
         */
        private void sendLocationMessage(UploadLocationMessage uploadLocationMessage) {
            if (uploadLocationMessage == null) return;
            String json = JSON.toJSONString(uploadLocationMessage);
            send(json);
            KLog.e("-----------------发送，推送位置报文\n" + json);
        }

        /**
         * 获取最近一次上传的专车信息
         */
        private void sendGetLocationOrder(String orderUuid) {
            if (TextUtils.isEmpty(orderUuid)) return;
            GetLocationOrderMessage message = new GetLocationOrderMessage(orderUuid);
            message.setClientUuid(clientUuid);
            String json = JSON.toJSONString(message);
            send(json);
            KLog.e("-----------------发送，获取最近一次上传的专车信息\n" + json);
        }

        /**
         * 处理推送消息
         *
         * @param message
         * @return
         */
        private String dealwithPushMessage(PushMessage message) {
            String content = message.getContent();
            try {
                SocketPushContent push = JSON.parseObject(content, SocketPushContent.class);
                if (push.data != null) {
                    push.orderUuid = TextUtils.isEmpty(push.data.mainOrderUuid)
                            ? push.data.orderUuid : push.data.mainOrderUuid;
                }
                if (push.opCode == null) {
                    return push.pushUuid;
                }

                // 通过EventBus将对应的消息发送出来
                switch (push.opCode) {
                    case SocketPushType.ORDER_MATCH_SUCCESS_TO_DRIVER: //订单匹配成功
                        KLog.e("---------------订单匹配成功");
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.ORDER_MATCH_SUCCESS, push.data.totalFare));
                        break;
                    case SocketPushType.ORDER_PUSH: //可抢订单推送
                        KLog.e("--------------可抢订单推送");
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.ORDER_PUSH, push));
                        if (ScreenUtil.isLockScreenOn(getApplicationContext()) && isTimingSend) {
                            mOrderRepository.ignoreList()
                                    .filter(strings -> {
                                        for (String string : strings) {
                                            if (string.equals(push.orderUuid)) {
                                                return null;
                                            }
                                        }
                                        return true;
                                    })
                                    .compose(RxUtil.applySchedulers())
                                    .subscribe(KLog::e, KLog::e, () -> {
                                        KLog.e("----------锁屏可抢订单");
                                        Intent intent = new Intent(SocketService.this, OrderPopupActivity.class);
                                        intent.putExtra(OrderPopupActivity.KEY_ORDER_UUID, push.orderUuid);
                                        intent.putExtra(OrderPopupActivity.KEY_ASSIGN, false);
                                        PendingIntent pi = PendingIntent.getActivity(SocketService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                                        Notification notification = new Notification.Builder(getApplicationContext())
                                                .setContentTitle(push.data.report)
                                                .setContentText("点击查看订单信息")
                                                .setContentIntent(pi)
                                                .setAutoCancel(true)
                                                .setSmallIcon(R.mipmap.ic_launcher)
                                                .build();
                                        mManager.notify(SocketPushType.ORDER_PUSH, notification);
                                        ScreenUtil.acquireScreen(getApplicationContext());
                                        SpeechUtil.speech(getApplicationContext(), push.data.report);
                                    });
                        }
                        break;
                    case SocketPushType.ORDER_DISTRIBUTE: //订单派送
                        KLog.e("----------订单派送");
                        orderUuid = push.orderUuid;
                        bizStatus = BizStatus.CARRY_PASSENGERS;
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.ORDER_DISTRIBUTE, push));
                        if (ScreenUtil.isLockScreenOn(getApplicationContext())) {
                            KLog.e("-----锁屏订单派送");
                            Intent intent = new Intent(SocketService.this, OrderDetailActivity.class);
                            intent.putExtra(OrderPopupActivity.KEY_ORDER_UUID, push.orderUuid);
                            intent.putExtra(OrderPopupActivity.KEY_ASSIGN, true);
                            PendingIntent pi = PendingIntent.getActivity(SocketService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                            Notification notification = new Notification.Builder(getApplicationContext())
                                    .setContentTitle("您有一个新的系统派单，请及时联系乘客")
                                    .setContentText("点击查看订单信息")
                                    .setContentIntent(pi)
                                    .setAutoCancel(true)
                                    .setSmallIcon(R.mipmap.ic_launcher)
                                    .build();
                            mManager.notify(SocketPushType.ORDER_DISTRIBUTE, notification);
                            ScreenUtil.acquireScreen(getApplicationContext());
                            SpeechUtil.speech(getApplicationContext(), push.data.report);
                        }
                        break;
                    case SocketPushType.ORDER_PASSENGER_CANCEL: {//乘客取消订单
                        KLog.e("-----乘客取消订单");
                        if (push.data.hasDriver == null) {
                            orderUuid = null;
                            bizStatus = BizStatus.EMPTY_DRIVING;
                        }
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.ORDER_PASSENGER_CANCEL, push));
                        if ((ScreenUtil.isLockScreenOn(getApplicationContext()) || ScreenUtil.isBackground(getApplicationContext()))
                                && push.data.hasDriver == null) {
                            Intent intent = new Intent(SocketService.this, OrderDetailActivity.class);
                            intent.putExtra(IConstants.ORDER_UUID, push.orderUuid);
                            PendingIntent pi = PendingIntent.getActivity(SocketService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                            Notification notification = new Notification.Builder(getApplicationContext())
                                    .setContentTitle("您有一个订单已被乘客取消")
                                    .setContentText("点击查看订单信息")
                                    .setContentIntent(pi)
                                    .setAutoCancel(true)
                                    .setSmallIcon(R.mipmap.ic_launcher)
                                    .build();
                            mManager.notify(SocketPushType.ORDER_PASSENGER_CANCEL, notification);
                            ScreenUtil.acquireScreen(getApplicationContext());
                            SpeechUtil.speech(getApplicationContext(), push.data.report);
                        }
                        break;
                    }
                    case SocketPushType.ORDER_PASSENGER_ORDER_PAYED: //用户已支付
                        KLog.e("-----用户已支付");
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.ORDER_PASSENGER_ORDER_PAYED, push));
                        if (ScreenUtil.isLockScreenOn(getApplicationContext()) || ScreenUtil.isBackground(getApplicationContext())) {
                            Intent intent = new Intent(SocketService.this, MyWalletActivity.class);
                            PendingIntent pi = PendingIntent.getActivity(SocketService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                            Notification notification = new Notification.Builder(getApplicationContext())
                                    .setContentTitle(push.data.content)
                                    .setContentText("点击查看")
                                    .setContentIntent(pi)
                                    .setAutoCancel(true)
                                    .setWhen(System.currentTimeMillis())
                                    .setSmallIcon(R.mipmap.ic_launcher)
                                    .build();
                            Random random = new Random();
                            mManager.notify(random.nextInt(100), notification);
                            SpeechUtil.speech(getApplicationContext(), push.data.report);
                            ScreenUtil.acquireScreen(getApplicationContext());
                        }
                        break;
                    case SocketPushType.ORDER_DISTRIBUTE_TO_OTHER: { //订单被改派
                        KLog.e("-----订单被改派");
                        orderUuid = null;
                        bizStatus = BizStatus.EMPTY_DRIVING;
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.ORDER_DISTRIBUTE_TO_OTHER, push));
                        if (ScreenUtil.isLockScreenOn(getApplicationContext()) || ScreenUtil.isBackground(getApplicationContext())) {
                            Intent intent = new Intent(SocketService.this, OrderDetailActivity.class);
                            intent.putExtra(IConstants.ORDER_UUID, push.orderUuid);
                            PendingIntent pi = PendingIntent.getActivity(SocketService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                            Notification notification = new Notification.Builder(getApplicationContext())
                                    .setContentTitle("您有一个订单已被改派给其他司机")
                                    .setContentText("点击查看订单信息")
                                    .setContentIntent(pi)
                                    .setAutoCancel(true)
                                    .setSmallIcon(R.mipmap.ic_launcher)
                                    .build();
                            mManager.notify(SocketPushType.ORDER_DISTRIBUTE_TO_OTHER, notification);
                            ScreenUtil.acquireScreen(getApplicationContext());
                            SpeechUtil.speech(getApplicationContext(), push.data.report);
                        }
                        break;
                    }
                    case SocketPushType.ORDER_CHANGE_DISTRIBUTE: { //收到改派订单
                        KLog.e("-----收到改派订单");
                        orderUuid = push.orderUuid;
                        bizStatus = BizStatus.CARRY_PASSENGERS;
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.ORDER_CHANGE_DISTRIBUTE, push));
                        if (ScreenUtil.isLockScreenOn(getApplicationContext())) {
                            KLog.e("-----锁屏订单派送");
                            Intent intent = new Intent(SocketService.this, OrderPopupActivity.class);
                            intent.putExtra(OrderPopupActivity.KEY_ORDER_UUID, push.orderUuid);
                            intent.putExtra(OrderPopupActivity.KEY_ASSIGN, true);
                            PendingIntent pi = PendingIntent.getActivity(SocketService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                            Notification notification = new Notification.Builder(getApplicationContext())
                                    .setContentTitle("您有一个新的系统派单，请及时联系乘客")
                                    .setContentText("点击查看订单信息")
                                    .setContentIntent(pi)
                                    .setAutoCancel(true)
                                    .setSmallIcon(R.mipmap.ic_launcher)
                                    .build();
                            mManager.notify(SocketPushType.ORDER_CHANGE_DISTRIBUTE, notification);
                            ScreenUtil.acquireScreen(getApplicationContext());
                            SpeechUtil.speech(getApplicationContext(), push.data.report);
                        }
                        break;
                    }
                    case SocketPushType.ORDER_SENDTASK_NEW_APPLY: //乘客申请行程
                        KLog.e("------乘客申请行程");
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.ORDER_SENDTASK_NEW_APPLY, push));
                        break;
                    case SocketPushType.ORDER_ADMIN_CLOSE: { //后台关闭订单
                        KLog.e("-----后台关闭订单");
                        orderUuid = null;
                        bizStatus = BizStatus.EMPTY_DRIVING;
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.ORDER_CLOSE, push));
                        if (ScreenUtil.isLockScreenOn(getApplicationContext()) || ScreenUtil.isBackground(getApplicationContext())) {
                            Intent intent = new Intent(SocketService.this, OrderDetailActivity.class);
                            intent.putExtra(IConstants.ORDER_UUID, push.orderUuid);
                            PendingIntent pi = PendingIntent.getActivity(SocketService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                            Notification notification = new Notification.Builder(getApplicationContext())
                                    .setContentTitle("您有一个订单已被管理员关闭")
                                    .setContentText("点击查看订单信息")
                                    .setContentIntent(pi)
                                    .setAutoCancel(true)
                                    .setSmallIcon(R.mipmap.ic_launcher)
                                    .build();
                            mManager.notify(SocketPushType.ORDER_ADMIN_CLOSE, notification);
                            ScreenUtil.acquireScreen(getApplicationContext());
                            SpeechUtil.speech(getApplicationContext(), push.data.report);
                        }
                        break;
                    }
                    case SocketPushType.ORDER_MATCH_THE_TIMEOVER:
                        KLog.e("------后台匹配超时");
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.ORDER_MATCH_THE_TIMEOVER, push));
                        break;
                    case SocketPushType.MODIFY_MONEY://修改金额
                        KLog.e("-----修改金额");
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.MODIFY_MONEY, push.data.totalFare));
                        break;
                    case SocketPushType.ORDER_HAS_BEEN_ROBBED:
                        KLog.e("-----订单已经被抢");
                        EventBus.getDefault().post(new OrderEvent(OrderEvent.ORDER_HAS_BEEN_ROBBED, push));
                        break;
                    case SocketPushType.SYSTEM_MESSAGE_NOTICE:
                        KLog.e("-----系统消息推送");
                        EventBus.getDefault().post(new MsgEvent(MsgEvent.SYSTEM_MESSAGE, push.data));
                        if (ScreenUtil.isLockScreenOn(getApplicationContext()) || ScreenUtil.isBackground(getApplicationContext())) {
                            // TODO: 2017/10/10 无法更新已读
                            MessageVO vo = new MessageVO();
                            vo.title = push.data.title;
                            vo.content = push.data.content;
                            vo.linkUrl = push.data.linkUrl;
                            vo.sendType = push.data.msgSendType;
                            vo.status = 1;
                            Random random = new Random();
                            Intent intent = new Intent(SocketService.this, MessageDetailsActivity.class);
                            intent.putExtra(MessageDetailsActivity.MESSAGE_DETAILS, vo);
                            PendingIntent pi = PendingIntent.getActivity(SocketService.this, random.nextInt(100), intent, PendingIntent.FLAG_UPDATE_CURRENT);
                            Notification notification = new Notification.Builder(getApplicationContext())
                                    .setContentTitle(push.data.msgSendType == 1 ? push.data.content : push.data.title)
                                    .setContentText("点击查看详情")
                                    .setContentIntent(pi)
                                    .setAutoCancel(true)
                                    .setWhen(System.currentTimeMillis())
                                    .setSmallIcon(R.mipmap.ic_launcher)
                                    .build();
                            mManager.notify(random.nextInt(100), notification);
                            ScreenUtil.acquireScreen(getApplicationContext());
                            if (push.data.msgSendType == 1) {
                                SpeechUtil.speech(getApplicationContext(), push.data.content);
                            } else {
                                SpeechUtil.speech(getApplicationContext(), push.data.title);
                            }
                        }
                        break;
                    case SocketPushType.ACCOUNT_WAS_CREATED:
                        isTimingSend = false;
                        EventBus.getDefault().post(new UserEvent(UserEvent.ACCOUNT_WAS_CREATED, push.data));
                        break;
                }
                KLog.i("\n" + content);
                return push.pushUuid;
            } catch (Exception e) {
                uploadErrorMsg(e.toString(), e.getMessage());
                KLog.e("-----> 解析数据出现异常");
                e.printStackTrace();
                return "";
            }
        }
    }

    private void uploadErrorMsg(String errorType, String errorMsg) {
        mUserRepository.uploadErrorMsg(errorType, errorMsg)
                .compose(RxUtil.applySchedulers())
                .subscribe(KLog::e, KLog::e);
    }

    /************************************* 定位相关 ************************************/
    private UploadOrderEntity mUpload;
    //时间戳
    private long mTimeStamp;
    //坐标
    private LatLng mCurrentPoint;
    private LatLng mLastPoint;
    //订单id
    private String orderUuid = null;
    //司机uuid
    private String driverUuid = null;
    //角度
    private float angle;
    //海拔高度
    private double elevation;
    //瞬时速度
    private float speed;
    //运营状态
    private int bizStatus = BizStatus.EMPTY_DRIVING;
    //行政区代码
    private String areaCode = null;

    /**
     * 开始定位
     */
    public void startLoacation() {
        mLocationClient = mAMapManager.getLocationClient();
        mLocationClient.setLocationListener(this);
    }

    /**
     * 监听定位到的地点
     *
     * @param aMapLocation
     */
    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {
        if (aMapLocation != null) {
            if (aMapLocation.getErrorCode() == 0) {
                mLocationFailCount = 0;
                EventBus.getDefault().post(new NetworkEvent(NetworkEvent.LOCATION_SUCCESS));
                // 实时导航时，记录定位信息
                EventBus.getDefault().post(new MapEvent(MapEvent.VIEW_LOCATION, aMapLocation));
                mTimeStamp = System.currentTimeMillis();
                mCurrentPoint = new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude());
                // 保存坐标
                mUserRepository.saveLatLng(mCurrentPoint);
                // 保存"省"、"市"
                mUserRepository.saveProvince(aMapLocation.getProvince());
                String city = aMapLocation.getCity();
                if (city != null && city.endsWith("市")) {
                    city = city.substring(0, city.length() - 1);
                }
                mUserRepository.saveCity(city);
                // 设置角度
                angle = aMapLocation.getBearing();
                // 设置海拔高度
                elevation = aMapLocation.getAltitude();
                // 设置速度
                speed = aMapLocation.getSpeed();
                // 区域编码
                areaCode = aMapLocation.getAdCode();
            } else {
                mLocationFailCount++;
                EventBus.getDefault().post(new NetworkEvent(NetworkEvent.LOCATION_FAILED));
                KLog.e("------定位失败，错误码：" + aMapLocation.getErrorCode());
            }
        } else {
            mLocationFailCount++;
            EventBus.getDefault().post(new NetworkEvent(NetworkEvent.LOCATION_FAILED));
            KLog.e("-----定位失败");
        }
    }

    /**
     * 获取"上传坐标"的报文
     *
     * @return
     */
    public UploadLocationMessage uploadLocationByTiming() {
        if (clientUuid == null || mCurrentPoint == null
                || mCurrentPoint.latitude == 0d || mCurrentPoint.longitude == 0d) {
            return null;
        }

        driverUuid = clientUuid;
        String locationUuid = mTimeStamp + "";
        LatLng oldPoint = mLastPoint;
        LatLng newPoint = mCurrentPoint;
        double distance = oldPoint == null ? 0d : (AMapUtils.calculateLineDistance(newPoint, oldPoint) / 1000);
        mLastPoint = mCurrentPoint;
        double lat = newPoint.latitude;
        double lng = newPoint.longitude;

        UploadLocationMessage uploadLocationMessage = new UploadLocationMessage(
                locationUuid, driverUuid, mUserRepository.getDriverType(),
                distance, lat, lng,
                angle, speed, elevation,
                areaCode, bizStatus, PositionType.AUTO);
        if (mUpload != null) { //有专车里程信息时，需要上传
            uploadLocationMessage.setPassengerUuid(mUpload.passengerUuid);
            uploadLocationMessage.setMileage(mUpload.mileage);
            uploadLocationMessage.setUploadTime(mUpload.uploadTime);
            uploadLocationMessage.setAccuracy(mUpload.accuracy);
        }
        uploadLocationMessage.setClientUuid(clientUuid);
        uploadLocationMessage.setOrderUuid(orderUuid);
        uploadLocationMessage.setCarLevelType(mCarLevelType);
        return uploadLocationMessage;
    }

    private UploadLocationMessage uploadLocationByTrigger(int bizStatus, String positionType, String orderUuid) {
        String locationUuid = mTimeStamp + "";
        driverUuid = clientUuid;

        UploadLocationMessage uploadLocationMessage = new UploadLocationMessage();
        uploadLocationMessage.setDriverUuid(driverUuid);
        uploadLocationMessage.setDriverType(mUserRepository.getDriverType());
        uploadLocationMessage.setLat(mCurrentPoint.latitude);
        uploadLocationMessage.setLng(mCurrentPoint.longitude);
        uploadLocationMessage.setDistance(0d);
        uploadLocationMessage.setAngle(angle);
        uploadLocationMessage.setSpeed(speed);
        uploadLocationMessage.setElevation(elevation);
        uploadLocationMessage.setAreaCode(areaCode);
        uploadLocationMessage.setBizStatus(bizStatus);
        uploadLocationMessage.setPositionType(positionType);
        uploadLocationMessage.setOrderUuid(orderUuid);
        uploadLocationMessage.setClientUuid(clientUuid);
        uploadLocationMessage.setLocationUuid(locationUuid);
        uploadLocationMessage.setCarLevelType(mCarLevelType);
        return uploadLocationMessage;
    }
}
